﻿using Castle.DynamicProxy;
using HelperCommon.AOP.MemoryCache;
using HelperCommon.Helper;
using System.Text.Json;
using static HelperCommon.CacheAttribut;

namespace HelperCommon.AOP
{
    public class MemoryAOP : IInterceptor
    {
        protected readonly IMemoryCaching caching;

        public MemoryAOP(IMemoryCaching memory)
        {
            caching = memory;
        }

        public void Intercept(IInvocation invocation)
        {
            #region 特性

            //var method = invocation.MethodInvocationTarget ?? invocation.Method;
            ////对当前方法的特性验证
            //var qCachingAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CachingAttribute)) as CachingAttribute;
            ////只有那些指定的才可以被缓存，需要验证
            //if (qCachingAttribute != null)
            //{
            //    //获取自定义缓存键
            //    var cacheKey2 = CustomCacheKey(invocation);
            //    //根据key获取相应的缓存值
            //    var cacheValue2 = caching.Get(cacheKey2);
            //    if (cacheValue2 != null)
            //    {
            //        //将当前获取到的缓存值，赋值给当前执行方法
            //        invocation.ReturnValue = cacheValue2;
            //        return;
            //    }
            //    //去执行当前的方法
            //    invocation.Proceed();
            //    //存入缓存
            //    if (!string.IsNullOrWhiteSpace(cacheKey2))
            //    {
            //        caching.Set(cacheKey2, invocation.ReturnValue);
            //    }
            //}
            #endregion

            //获取自定义缓存键
            var cacheKey = CustomCacheKey(invocation);
            //根据key获取相应的缓存值
            var cacheValue = caching.Get(cacheKey);
            if (cacheValue != null)
            {
                //将当前获取到的缓存值，赋值给当前执行方法
                invocation.ReturnValue = cacheValue;
                return;
            }
            //去执行当前的方法
            invocation.Proceed();
            //存入缓存
            if (!string.IsNullOrWhiteSpace(cacheKey))
            {
                caching.Set(cacheKey, invocation.ReturnValue);
            }
        }

        /// <summary>
        /// object 转 string
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected static string GetArgumentValue(object arg)
        {
            if (arg is DateTime || arg is DateTime?)
            {
                return ((DateTime)arg).ToString("yyyyMMddHHmmss");
            }

            if (arg is string || arg is ValueType || arg is Nullable)
            {
                return arg.ToString();
            }

            if (arg != null)
            {
                if (arg.GetType().IsClass)
                {
                    return MD5Helper.MD5Encrypt16(JsonSerializer.Serialize(arg));
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// 自定义缓存的key
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        protected string CustomCacheKey(IInvocation invocation)
        {
            var typeName = invocation.TargetType.Name;
            var methodName = invocation.Method.Name;
            var methodArguments = invocation.Arguments.Select(GetArgumentValue).Take(3).ToList();//获取参数列表，最多三个

            string key = $"{typeName}:{methodName}:";
            foreach (var param in methodArguments)
            {
                key = $"{key}{param}:";
            }
            return key.TrimEnd(':');
        }
    }
}